﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using StockShark.Models;

namespace StockShark.BusinessModels
{
    public class TradeCenter
    {

        public static void ExecuteTransactions(bool sharesCont, bool sharesFixing, bool currencies, bool materials)
        {
            StockSharkDB db = new StockSharkDB();
            var orders = db.Orders
                .Where(r => r.Paper.CurrentPrice > 0)
                .OrderBy(r => r.IssuingDate)
                .ToList()
                .Where(r =>
                    (sharesCont && r.Paper.GetType().Name == "Share" && ((Share)(r.Paper)).Fixing == false) ||
                    (sharesFixing && r.Paper.GetType().Name == "Share" && ((Share)(r.Paper)).Fixing == true) ||
                    (currencies && r.Paper.GetType().Name == "Currency") ||
                    (materials && r.Paper.GetType().Name == "Material"));

            foreach (var order in orders)
            {
                if (order.BuyNotSell && (order.PriceLimit == 0 || order.PriceLimit >= order.Paper.CurrentPrice))
                {
                    var comm = GameProperties.CalculateCommission(order.Total, order.Paper.GetType().Name.ToLower());
                    var ba = order.BrokerageAccount;
                    if (order.Total + comm <= ba.Balance)
                    {
                        ba.Balance -= (order.Total + comm);
                        ba.ExecutedTransactions.Add(new ExecutedTransaction
                        {
                            BuyNotSell = true,
                            ExecutionDate = DateTime.Now,
                            Commission = comm,
                            Paper = order.Paper,
                            Quantity = order.Quantity,
                            UnitPrice = order.Paper.CurrentPrice
                        });
                        if (ba.OwnedInstruments.Where(r => r.PaperId == order.PaperId).Count() == 0)
                        {
                            ba.OwnedInstruments.Add(new OwnedInstrument
                            {
                                Paper = order.Paper,
                                Quantity = order.Quantity
                            });
                        }
                        else
                        {
                            ba.OwnedInstruments.Single(r => r.PaperId == order.PaperId).Quantity += order.Quantity;
                        }
                        db.Orders.Remove(order);
                        db.SaveChanges();
                    }
                    else if (order.AllowPartial)
                    {
                        //todo
                    }
                }
                else if (!order.BuyNotSell && (order.PriceLimit == 0 || order.PriceLimit <= order.Paper.CurrentPrice))
                {
                    var comm = GameProperties.CalculateCommission(order.Total, order.Paper.GetType().Name.ToLower());
                    var ba = order.BrokerageAccount;
                    var owned = db.OwnedInstruments.Single(r => r.PaperId == order.PaperId);
                    if (order.Quantity <= owned.Quantity && comm <= ba.Balance + order.Total)
                    {
                        ba.Balance += (order.Total - comm);
                        ba.ExecutedTransactions.Add(new ExecutedTransaction
                        {
                            BuyNotSell = false,
                            ExecutionDate = DateTime.Now,
                            Commission = comm,
                            Paper = order.Paper,
                            Quantity = order.Quantity,
                            UnitPrice = order.Paper.CurrentPrice
                        });
                        owned.Quantity -= order.Quantity;
                        if (owned.Quantity == 0)
                        {
                            db.OwnedInstruments.Remove(owned);
                        }
                        db.Orders.Remove(order);
                        db.SaveChanges();
                    }
                    else if (order.AllowPartial)
                    {
                        //todo
                    }
                }
                
            }                           
        }

    }
}